#pragma once

#ifndef PACMAN_ENVIRONMENT_H
#define PACMAN_ENVIRONMENT_H

#include "CpuZ80.h"
#include "VideoHardware.h"
#include "SoundHardware.h"

enum DipSwitchSettings
{
	CoinsPerGame_FreePlay		= 0,
	CoinsPerGame_1Coin			= 1,
	CoinsPerGame_1Coin2Games	= 2,
	CoinsPerGame_2Coins			= 3,
	NumberOfLives_1Life			= 0,
	NumberOfLives_2Lives		= 4,
	NumberOfLives_3Lives		= 8,
	NumberOfLives_5Lives		= 12,
	BonusScore_10000			= 0,
	BonusScore_15000			= 16,
	BonusScore_20000			= 32,
	BonusScore_None				= 48,
	Difficulty_Hard				= 0,
	Difficulty_Normal			= 64,
	GhostNames_Alternate		= 0,		// I think names were customizable by writing in the rom. Default alternate names
											// are "AAAAAA" "BBBBBB", etc.
	GhostNames_Normal			= 128
};

class PacmanEnvironment : public CpuZ80Environment
{

public:

	PacmanEnvironment();
	~PacmanEnvironment();

	// Main Update function -> Updates the CPU, calls interrupts
	void					Update(size_t cycles);

	void					SetInput(byte_t inputs[2]);

	bool					IsRunning() const;

	const VideoHardware *	GetVideoHW() const;
	const SoundHardware *	GetSoundHW() const;

	// Play a sound in the buffer
	void					Play(sword_t * buffer, size_t size, size_t sampleRate);

	// Set Dip Switch Settings
	void					SetDipSwitchSettings(byte_t settings);
	byte_t					GetDipSwitchSettings() const;

private:

	byte_t					ReadByte(word_t address) const;
	void					WriteByte(byte_t data8, word_t address);

	byte_t					ReadBytePort(byte_t port) const;
	void					WriteBytePort(byte_t data, byte_t port);

private:

	CpuZ80 *				m_cpu;
	byte_t *				m_memory;
	bool					m_isRunning;

	byte_t					m_interruptVector;

	VideoHardware *			m_videoHw;
	SoundHardware *			m_soundHw;


	// Dipswitches and I/O
	bool					m_interruptEnabled;
	byte_t					m_input0;
	byte_t					m_input1;

	byte_t					m_dipSwitch;
};

inline bool PacmanEnvironment::IsRunning() const
{
	return m_isRunning;
}

inline const VideoHardware * PacmanEnvironment::GetVideoHW() const
{
	return m_videoHw;
}

inline const SoundHardware * PacmanEnvironment::GetSoundHW() const
{
	return m_soundHw;
}

inline void PacmanEnvironment::SetDipSwitchSettings(byte_t settings)
{
	m_dipSwitch = settings;
}

inline byte_t PacmanEnvironment::GetDipSwitchSettings() const
{
	return m_dipSwitch;
}
#endif
